package com.self.auth.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;

import java.security.KeyPair;

/**
 * @version v1.0
 * @ClassName: AuthConfig
 * @Description:
 * @Author: Mac
 * @Date: 2022/5/22 21:27
 */
@EnableAuthorizationServer
@Configuration
public class AuthConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private AuthenticationManager authenticationManager;

    @Qualifier("userSecurityServiceImpl")
    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private RedisConnectionFactory redisConnectionFactory;

    /**
     * @Title: 配置第三方客户端
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("exchange-api") //第三方客户端名称（用户名）
                .secret(passwordEncoder.encode("exchange-secret")) //第三方客户端密码
                .scopes("all")
                .authorizedGrantTypes("password","refresh_token") //授权类型
                .accessTokenValiditySeconds(7 * 24 * 3600) //7天
                .refreshTokenValiditySeconds(30 * 7 * 24 * 3600)  //30天
                .and()
                .withClient("inside-app")  //用户服务在没有客户请求时，内部之间调用的场景，例如：定时任务
                .secret(passwordEncoder.encode("inside-secret"))
                .scopes("all")
                .authorizedGrantTypes("client_credentials") //授权类型.客户端认证
                .accessTokenValiditySeconds(7 * 24 * 3600); //7天

    }

    /**
     * @Title: 设置授权管理器
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager)
                .userDetailsService(userDetailsService)
                //.tokenStore(redisTokenStore()); //redis存贮token
                .tokenStore(jwtTokenStore())  //jwt存储
                .tokenEnhancer(jwtAccessTokenConverter()); //token增强器
    }

    private TokenStore jwtTokenStore() {
        return new JwtTokenStore(jwtAccessTokenConverter());
    }

    /**
     * @Title: 创建一个jwttoken转化器，加载jwt私钥，
     * @Description: 
     * @Param []
     * @Return org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter
     * @Author Mac
     * @Throws
     * @Date 2022/5/28 11:36
     */
    private JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
        ClassPathResource classPathResource = new ClassPathResource("matchexchange.jks");
        KeyStoreKeyFactory keyFactory = new KeyStoreKeyFactory(classPathResource,"matchexchange".toCharArray());
        jwtAccessTokenConverter.setKeyPair(keyFactory.getKeyPair("matchexchange","matchexchange".toCharArray()));
        return jwtAccessTokenConverter;
    }

    public TokenStore redisTokenStore(){
        return new RedisTokenStore(redisConnectionFactory);
    }
}
